#include "aacencoder.h"
#include"dlog.h"

AACEncoder::AACEncoder()
{

}

AACEncoder::~AACEncoder()
{
    if(_ctx)
    {
        avcodec_free_context(&_ctx);
    }
}

RET_CODE AACEncoder::init(const Properties &properties)
{

    // 获取参数
    _sample_rate = properties.GetProperty("sample_rate", 48000);
    _bit_rate = properties.GetProperty("bit_rate", 128*1024);
    _channels = properties.GetProperty("channels", 2);
    _channel_layout = properties.GetProperty("channel_layout", (int)av_get_default_channel_layout(_channels));
    // 查找编码器
    _codec = avcodec_find_encoder(AV_CODEC_ID_AAC); //这里不算硬编码，因为我这个类就是AAC的编码器
    if(!_codec)
    {
        LogError("AAC: Not find encoder");
        return RET_ERR_MISMATCH_CODE;
    }
    _ctx = avcodec_alloc_context3(_codec);
    if(!_ctx)
    {
        LogError("AAC: avodec_alloc_context3 failed");
        return RET_ERR_OUTOFMEMORY;
    }
    // 设置编码参数
    _ctx->channels = _channels;
    _ctx->channel_layout = _channel_layout;
    _ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; //默认的AAC编码器需要使用planar格式的PCM
    _ctx->sample_rate = _sample_rate;
    _ctx->bit_rate = _bit_rate;
    // 打开编码器
    if(avcodec_open2(_ctx, _codec, NULL) < 0)
    {
        LogError("AAC: cannot avcodec_open2");
        avcodec_free_context(&_ctx);
        return RET_FAIL;
    }
    return RET_OK;
}

AVPacket *AACEncoder::encode(AVFrame *frame, const int64_t pts, int flush, int *pktFrame, RET_CODE *ret)
{
    int ret1 = 0;
    *pktFrame = 0;
    if(!_ctx)
    {
        *ret = RET_FAIL;
        LogError("ACC: NO context");
        return NULL;
    }
    // 如果传入了帧，那么就读取这个帧里面的数据进行编码
    if(frame)
    {
        frame->pts = pts;
        ret1 = avcodec_send_frame(_ctx, frame);
        if(ret1 < 0)
        {
            char buf[1024] = {0};
            av_strerror(ret1, buf, sizeof(buf) - 1);
            LogError("avcodec_send_frame failed: %s", buf);
            *pktFrame = 1;//标记是对帧操作的时候报错了
            if(ret1 == AVERROR(EAGAIN)) //此时编码器中的frame数据满了，再往里面塞frame放不进了，需要快点读取packet数据。
            {
                *ret = RET_ERR_EAGAIN;
                return NULL;
            }
            else if(ret1 == AVERROR_EOF) //文件读取完毕
            {
                *ret = RET_ERR_EOF;
                return NULL;
            }
            else //真正的报错，encoder只能销毁了
            {
                *ret = RET_FAIL;
                return NULL;
            }
        }
    }
    // 如果发送的数据发送完了，需要把编码器中剩余的一丢丢内存也读取出来【只能调用一次，由调用者控制】
    if(flush)
    {
        avcodec_flush_buffers(_ctx);
    }
    AVPacket *packet = av_packet_alloc();
    ret1 = avcodec_receive_packet(_ctx, packet);
    if(ret1 < 0) {
            LogError("AAC: avcodec_receive_packet ret:%d", ret1);
            av_packet_free(&packet);
            *pktFrame = 0;//标记是对包操作的时候报错了
            if(ret1 == AVERROR(EAGAIN))  // 此时编码器中的数据不够，无法解析出一个完整的包，需要继续发送frame我们才有packet读取
            {
                *ret = RET_ERR_EAGAIN;
                return NULL;
            }
            else if(ret1 == AVERROR_EOF) // 文件读取完毕，不能在读取出来packet来了
            {
                *ret = RET_ERR_EOF;
                return NULL;
            }
            else  // 真正报错，这个encoder就只能销毁了
            {
                *ret = RET_FAIL;
                return NULL;
            }
    }
    else
    {
        *ret = RET_OK;
        return packet;
    }
}

///
/// \brief AACEncoder::getAdtsHeader
/// \param adtsHeader
/// \param aacLength packet的长度
/// \return
///
RET_CODE AACEncoder::getAdtsHeader(uint8_t *adtsHeader, int aacLength)
{
    uint8_t freqIdx = 0;    //0: 96000 Hz  3: 48000 Hz 4: 44100 Hz
    switch (_ctx->sample_rate)
    {
    case 96000: freqIdx = 0; break;
    case 88200: freqIdx = 1; break;
    case 64000: freqIdx = 2; break;
    case 48000: freqIdx = 3; break;
    case 44100: freqIdx = 4; break;
    case 32000: freqIdx = 5; break;
    case 24000: freqIdx = 6; break;
    case 22050: freqIdx = 7; break;
    case 16000: freqIdx = 8; break;
    case 12000: freqIdx = 9; break;
    case 11025: freqIdx = 10; break;
    case 8000: freqIdx = 11; break;
    case 7350: freqIdx = 12; break;
    default:
        LogError("can't support sample_rate:%d");
        freqIdx = 4;
        return RET_FAIL;
    }
    uint8_t ch_cfg = _ctx->channels;
    uint32_t frame_length = aacLength + 7;
    adtsHeader[0] = 0xFF;
    adtsHeader[1] = 0xF1;
    adtsHeader[2] = ((_ctx->profile) << 6) + (freqIdx << 2) + (ch_cfg >> 2);
    adtsHeader[3] = (((ch_cfg & 3) << 6) + (frame_length  >> 11));
    adtsHeader[4] = ((frame_length & 0x7FF) >> 3);
    adtsHeader[5] = (((frame_length & 7) << 5) + 0x1F);
    adtsHeader[6] = 0xFC;
    return RET_OK;
}
